package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.core.RoleEnum;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.entity.AppFile;
import la.iok.hzsvn.lewin.movie.entity.AppPackageItem;
import la.iok.hzsvn.lewin.movie.mapper.AppPackageItemMapper;
import la.iok.hzsvn.lewin.movie.model.AppPackageItemParam;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.NotNullElement;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.utils.PathUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;

@Service
public class AppPackageItemServiceImpl extends BaseServiceImpl<AppPackageItem, AppPackageItemMapper,Long> implements AppPackageItemService {
    private final AppFileService appFileService;
    private final WebDfsService webDfsService;
    public AppPackageItemServiceImpl(AppPackageItemMapper mapper, AppFileService appFileService, WebDfsService webDfsService) {
        super(mapper);
        this.appFileService = appFileService;
        this.webDfsService = webDfsService;
    }

    @Transactional
    @Override
    public Long save(@NotNull Token token, @NotNull AppPackageItemParam param) {
        token.validAnyAuthority(RoleEnum.Admin);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(param.getAppPackageId(),"应用","应用程序id不能为空");
        String fileName = ErrorCode.PROPERTY_CHECK_ERROR.assertNotBlank(param.getFileName(),"文件名","文件名不能为空");
        String digest = ErrorCode.PROPERTY_CHECK_ERROR.assertNotBlank(param.getDigest(),"摘要","文件摘要信息不能为空");
        String relativePath = ErrorCode.PROPERTY_CHECK_ERROR.assertNotBlank(param.getRelativePath(),"相对目录","文件相对目录不能为空");
        AppPackageItem entity = new AppPackageItem();
        entity.setAppPackageId(param.getAppPackageId());
        entity.setRelativePath(relativePath);
        AppFile file = appFileService.select(digest);
        if(file!=null){
            if(webDfsService.exist(webDfsService.dfsFile(file.getPath()))){
                entity.setFileId(file.getId());
                appFileService.increment(file.getId());
            }
        }else{
            entity.setFileId(appFileService.save(fileName, webDfsService.storePath(digest,fileName),digest));
            appFileService.increment(entity.getFileId());
        }
        insertSelective(entity);
        return entity.getId();
    }

    @Transactional
    @Override
    public void delete(@NotNull Token token, @Nullable Long id) {
        token.validAnyAuthority(RoleEnum.Admin);
        AppPackageItem entity = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(entity);
        appFileService.decrement(entity.getFileId());
        delete(id);
    }

    @Transactional
    @Override
    public void deletePackageItems(@Nullable Long appPackageId) {
        if(appPackageId == null){
            return;
        }
        List<AppPackageItem> list = listByProperty("appPackageId",appPackageId);
        list.forEach(item->appFileService.decrement(item.getFileId()));
        delete("appPackageId",appPackageId);
    }

    @Transactional
    @Override
    public void updateFile(Token token, Long id, Long fileId) {
        token.validAnyAuthority(RoleEnum.Admin);
        AppPackageItem entity = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(entity,id);
        appFileService.decrement(entity.getFileId());
        update(id,"fileId", fileId);
        appFileService.increment(fileId);
    }

    @Transactional
    @Override
    public void uploadFile(@NotNull Token token, @NotNull Long id, MultipartFile file) {
        token.validAnyAuthority(RoleEnum.Admin);
        AppPackageItem entity = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(entity,id);
        Long fileId = appFileService.uploadFile(file);
        appFileService.decrement(entity.getFileId());
        update(id,"fileId",fileId);
        appFileService.increment(fileId);
    }

    @Override
    public boolean exist(@NotNull Long id) {
        AppPackageItem item = select(id);
        if(item == null){
            return false;
        }
        return appFileService.exist(item.getFileId());
    }

    @NotNull
    @NotNullElement
    @Override
    public List<AppPackageItem> packageFiles(@Nullable Long appPackageId) {
        if(appPackageId == null){
            return Collections.emptyList();
        }
        return listByProperty("appPackageId",appPackageId);
    }

    @Override
    public void allFileExist(Long appPackageId) {
        List<AppPackageItem> list = packageFiles(appPackageId);
        ErrorCode.PROPERTY_CHECK_ERROR.assertNotEmpty(list,"程序文件","程序包不包含任何文件");
        list.forEach(item->{
            ErrorCode.APP_FILE_NOT_EXIST.assertTrue(appFileService.exist(item.getFileId()),item.getRelativePath());
        });
    }

    @Override
    public void downloadFile(@NotNull HttpServletResponse response, @Nullable Long id) {
        AppPackageItem item = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(item,id);
        appFileService.downloadFile(response, item.getFileId());
    }

    @Override
    public void download2Local(String appPath, AppPackageItem item) throws IOException {
        String filePath = PathUtils.join(appPath,item.getRelativePath());
        File f = new File(filePath);
        File p = f.getParentFile();
        if(!p.exists()){
            p.mkdirs();
        }
        try(OutputStream os = new FileOutputStream(filePath)){
            appFileService.downloadFile(os, appFileService.select(item.getFileId()));
        }
    }

    @Nullable
    @Override
    public String digest(@Nullable Long id) {
        AppPackageItem item = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(item,id);
        return appFileService.digest(item.getFileId());
    }

    @Override
    public String storePath(Long id) {
        AppPackageItem item = select(id);
        ErrorCode.RECORD_NOT_EXIST.assertNotNull(item,id);
        return appFileService.storePath(item.getFileId());
    }
}
